package com.linked.order.order.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.linked.order.feign.IGoodsFeign;
import com.linked.order.feign.IPayFeign;
import com.linked.order.feign.IStoreFeign;
import com.linked.order.order.bean.param.CreateOrderParam;
import com.linked.order.order.bean.po.GoodsDetailPO;
import com.linked.order.order.bean.po.OrderInfoPO;
import com.linked.order.order.service.IGoodsDetailService;
import com.linked.order.order.service.IOrderHandleService;
import com.linked.universal.bean.goods.goods.LinkedGoods;
import com.linked.universal.bean.pay.param.WaitingPayCreateParam;
import com.linked.universal.bean.pay.result.PayResultPush;
import com.linked.universal.common.LinkedPrompt;
import com.linked.universal.common.LinkedResult;
import com.linked.universal.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

/**
 * @author :dbq
 * @date : 2023/5/26 14:24
 * @description : desc
 */
@RestController
@Slf4j
@RequestMapping("orderhandle")
public class OrderHandleController {

    private final IOrderHandleService orderHandleService;

    private final ObjectMapper mapper;

    private final IGoodsFeign goodsFeign;

    private final IGoodsDetailService goodsDetailService;

    private final IPayFeign payFeign;

    private final IStoreFeign storeFeign;

    private final TransactionTemplate transactionTemplate;

    public OrderHandleController(IStoreFeign storeFeign, TransactionTemplate transactionTemplate,
                                 IPayFeign payFeign, IGoodsDetailService goodsDetailService,
                                 IGoodsFeign goodsFeign, IOrderHandleService orderHandleService,
                                 ObjectMapper mapper) {
        this.orderHandleService = orderHandleService;
        this.mapper = mapper;
        this.goodsFeign = goodsFeign;
        this.goodsDetailService = goodsDetailService;
        this.payFeign = payFeign;
        this.transactionTemplate = transactionTemplate;
        this.storeFeign = storeFeign;
    }

    @PostMapping("createOrder")
    Result createOrder(@RequestBody CreateOrderParam param) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("创建订单接口 入参：{}", mapper.writeValueAsString(param));
        }
        return transactionTemplate.execute(action -> {

            OrderInfoPO orderInfo = new OrderInfoPO();

            StringBuilder idBuilder = new StringBuilder();
            DecimalFormat decimalFormat = new DecimalFormat("000000");
            idBuilder.append("DD").append(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"))).append(decimalFormat.format((int) (Math.random() * 1000000 + 1)));
            orderInfo.setOrderId(idBuilder.toString());
            /**
             * 一、获取商品信息
             * */
            LinkedGoods goods = goodsFeign.queryLinkedGoods(param.getGoodsVersionId());


            /**
             * 二、计算订单总价格
             * */
            Double totalPrice = goods.getVersionPrice() * param.getGoodsCount();


            /**
             * 三、创建待支付订单
             * */
            WaitingPayCreateParam payParam = new WaitingPayCreateParam();
            payParam.setOrderId(orderInfo.getOrderId());
            payParam.setUserId(param.getUserId());
            payParam.setMoneyAmount(totalPrice);
            LinkedResult payRes = payFeign.createWaitingPay(payParam);
            if (payRes == null || !payRes.isSuccess()) {
                log.info("创建支付单失败！");
                action.setRollbackOnly();
                return Result.ok(false, LinkedPrompt.CREATE_FAILURE);
            }

            /**
             * 四、保存订单数据
             * */
            orderInfo.setPayId((String) payRes.getData());
            orderInfo.setUserId(param.getUserId());
            orderInfo.setGoodsCount(param.getGoodsCount());
            orderInfo.setTotalPrice(totalPrice);
            orderInfo.setGoodsVersionId(param.getGoodsVersionId());
            orderInfo.setAddressId(param.getAddressId());
            boolean orderRet = orderHandleService.createOrder(orderInfo);
            if (!orderRet) {
                action.setRollbackOnly();
                log.info("创建订单失败！");
                return Result.ok(false, LinkedPrompt.CREATE_FAILURE);
            }
            /**
             * 五、保存商品信息
             * */
            GoodsDetailPO tmpGoods = new GoodsDetailPO(goods);
            tmpGoods.setOrderId(orderInfo.getOrderId());
            boolean goodsRet = goodsDetailService.saveGoodsDetail(tmpGoods);
            if (!goodsRet) {
                log.info("保存商品失败！");
                action.setRollbackOnly();
                return Result.ok(false, LinkedPrompt.CREATE_FAILURE);
            }

            /**
             * 六、扣减库存
             * */
            LinkedResult storeRet = storeFeign.reduceInventory(orderInfo.getOrderId(), param.getGoodsVersionId(), param.getGoodsCount());
            if (storeRet == null || !storeRet.isSuccess()) {
                log.info("扣减库存失败！");
                action.setRollbackOnly();
                return Result.ok(false, LinkedPrompt.CREATE_FAILURE);
            }
            return Result.success();
        });
    }

    @PostMapping("receiverPayResult")
    LinkedResult receiverPayResult(@RequestBody PayResultPush param) throws Exception {
        if (log.isInfoEnabled()) {
            log.info("接收支付结果接口 入参：{}", mapper.writeValueAsString(param));
        }
        /**
         * 1、修改订单状态
         * */
        boolean updateRet = orderHandleService.updateOrderStatus(param.getPayId(), 2);
        if (!updateRet) {
            log.info("修改订单失败！");
        }
        /**
         * 2、回调支付项目，通知已接受推送消息
         * */
        boolean sendRet = orderHandleService.sendReceivedMessage(param.getPayId());
        if (!sendRet) {
            log.info("发送已接受消息失败！");
        }
        return LinkedResult.Success();
    }
}
